package router

import (
	"context"
	"fmt"
	wangxu2 "github.com/beherochuling/beesoft_api/app/service/org/wangxu"
	"github.com/gogf/gf/v2/container/gset"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/util/gconv"
	"net/http"

	"github.com/beherochuling/beesoft_api/app/helper/net/websocket"
)

func init() {
	websocket.OnOpen(func(ws *websocket.Websocket) {
		if wangxu2.IsFormer(ws) {
			wangxu2.LetsviewCallback.OnOpen(ws)
			return
		}

		fmt.Printf("Websocket OnOpen url: %s ws: %s\n", ws.Request.URL, gconv.String(ws))
		ws.Write(&websocket.JsonObject{
			Status:  http.StatusOK,
			Message: fmt.Sprintf("你好，用户 %d", ws.UserId),
			Data: g.Map{
				"fd":  ws.FD,
				"now": gtime.Now(),
			},
		})
		websocket.Broadcast(ws.GroupId, &websocket.JsonObject{
			Status:  http.StatusOK,
			Message: fmt.Sprintf("用户 %d 上线了，广播所有用户，更新在线用户列表", ws.UserId),
			Data: g.Map{
				"users": websocket.GetUsers(ws.GroupId),
			},
		})
	})
	websocket.OnClose(func(ws *websocket.Websocket) {
		wangxu2.LetsviewCallback.OnClose(ws)

		fmt.Printf("Websocket OnClose group_id: %s user_id: %d fd: %d\n", ws.GroupId, ws.UserId, ws.FD)
		websocket.Broadcast(ws.GroupId, &websocket.JsonObject{
			Status:  http.StatusOK,
			Message: fmt.Sprintf("用户 %d 下线了，广播所有用户，更新在线用户列表", ws.UserId),
			Data: g.Map{
				"users": websocket.GetUsers(ws.GroupId),
			},
		}, ws.FD)
	})
	websocket.OnError(func(ws *websocket.Websocket, err error) {
		fmt.Printf("Websocket OnError: %+v\n", err)
		glog.Error(context.Background(), err)
	})
	websocket.OnMessage(func(ws *websocket.Websocket, msg *websocket.ActionMessage) {
		fmt.Printf("Websocket OnMessage: %s\n", gconv.String(msg))

		if msg.Options != nil {
			existGroupIds := gset.NewStrSet()
			if len(msg.Options.ToGroups) > 0 {
				for _, groupId := range msg.Options.ToGroups {
					if websocket.GroupExists(groupId) {
						existGroupIds.Add(groupId)
					}
				}
			}
			notExistGroupIds := gset.NewStrSetFrom(msg.Options.ToGroups).Diff(existGroupIds)

			existUserIds := gset.NewIntSet()
			if len(msg.Options.ToUsers) > 0 {
				for _, userId := range msg.Options.ToUsers {
					if websocket.UserExists(ws.GroupId, userId) {
						existUserIds.Add(userId)
					}
				}
			}
			notExistUserIds := gset.NewIntSetFrom(msg.Options.ToUsers).Diff(existUserIds)

			statusCode := http.StatusOK
			if notExistGroupIds.Size() > 0 || notExistUserIds.Size() > 0 {
				statusCode = http.StatusNotFound
			}

			ws.Write(&websocket.JsonObject{
				Status:  statusCode,
				Message: http.StatusText(statusCode),
				Data: g.Map{
					"not_exist_group_ids": notExistGroupIds,
					"group_ids":           existGroupIds,
					"not_exist_user_ids":  notExistUserIds,
					"user_ids":            existUserIds,
				},
			})

			if existGroupIds.Size() > 0 {
				for _, groupId := range existGroupIds.Slice() {
					websocket.Broadcast(groupId, &websocket.JsonObject{
						Status:  http.StatusOK,
						Message: fmt.Sprintf("我是广播，把消息发给 [%s] 组内所有用户", groupId),
						Action:  msg.Action,
						Options: msg.Options,
						Data:    msg.Data,
					})
				}
			}

			if existUserIds.Size() > 0 {
				websocket.SendToUsers(ws.GroupId, existUserIds.Slice(), &websocket.JsonObject{
					Status:  http.StatusOK,
					Message: fmt.Sprintf("我是单播，只把消息发给指定用户: %v", msg.Options.ToUsers),
					Action:  msg.Action,
					Options: msg.Options,
					Data:    msg.Data,
				})
			}
		}
	})
	websocket.OnGroupOpen(func(ws *websocket.Websocket, groupId string) {
		fmt.Printf("Websocket OnGroupOpen group_id: %s user_id: %d fd: %d\n", groupId, ws.UserId, ws.FD)
		websocket.Broadcast(ws.GroupId, &websocket.JsonObject{
			Status:  http.StatusOK,
			Message: fmt.Sprintf("用户 %d 下线了，广播所有用户，更新在线用户列表", ws.UserId),
			Data: g.Map{
				"users": websocket.GetUsers(ws.GroupId),
			},
		}, ws.FD)
	})
	websocket.OnGroupClose(func(groupId string, allClosed bool) {
		fmt.Printf("Websocket OnGroupClose group_id: %s allClosed: %t\n", groupId, allClosed)
	})
	websocket.OnGroupJoin(func(ws *websocket.Websocket, data *websocket.ActionMessage, joinedGroupId string) {
		fmt.Printf("Websocket OnGroupJoin group_id: %s\n", joinedGroupId)
		websocket.Broadcast(joinedGroupId, &websocket.JsonObject{
			Status:  http.StatusOK,
			Message: fmt.Sprintf("用户 %d 加入了房间 [%s]，广播所有用户，更新在线用户列表", ws.UserId, joinedGroupId),
			Data: g.Map{
				"users": websocket.GetUsers(joinedGroupId),
			},
		})
	})
	websocket.OnGroupExit(func(ws *websocket.Websocket, data *websocket.ActionMessage, exitedGroupId string) {
		fmt.Printf("Websocket OnGroupExit group_id: %s\n", exitedGroupId)
		ws.Write(&websocket.JsonObject{
			Status: http.StatusOK,
			Data: g.Map{
				"data": fmt.Sprintf("%d 离开房间 [%s]，当前默认房间为 [%s]", ws.UserId, exitedGroupId, ws.GroupId),
				"now":  gtime.Now(),
			},
		})

		websocket.Broadcast(exitedGroupId, &websocket.JsonObject{
			Status:  http.StatusOK,
			Message: fmt.Sprintf("%d 离开房间 [%s]", ws.UserId, exitedGroupId),
			Data: g.Map{
				"users": websocket.GetUsers(exitedGroupId),
			},
		})
	})
}
